package com.hbnrtech.sip.datasource.config;

import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liuduo
 * @date 2023/5/13 10:46
 */
@Configuration
public class DataSourceConfig {

    @Bean(DataSourceKey.DEFAULT_DB)
    @ConditionalOnProperty(value = "default.datasource.name", havingValue = DataSourceKey.DEFAULT_DB)
    @ConfigurationProperties(prefix = "default.datasource")
    @Primary
    public HikariDataSource defaultDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean
    public DataSource routingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceKey.DEFAULT_DB, defaultDataSource());

        RoutingDataSource routingDataSource = new RoutingDataSource();
        routingDataSource.setDefaultTargetDataSource(defaultDataSource());
        routingDataSource.setTargetDataSources(targetDataSources);
        routingDataSource.afterPropertiesSet();

        return routingDataSource;
    }

    /**
     * 配置 SqlSessionFactoryBean
     * 在这里是为了将 MyBatis 的 mapper 位置和持久层接口的别名设置到 Bean
     * 的属性中，如果没有使用 *.xml 则可以不用该配置，否则将会产生 invalid bound statement 异常
     */
    @Bean("sqlSessionFactory")
    @ConfigurationProperties(prefix = "mybatis")
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        // 配置数据源，此处配置为关键配置，如果没有将 routingDataSource 作为数据源则不能实现切换
        sqlSessionFactoryBean.setDataSource(routingDataSource());

        sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:sqlMapper/*.xml"));

        return sqlSessionFactoryBean;
    }

    @Bean
    public PlatformTransactionManager txManager() {
        return new DataSourceTransactionManager(routingDataSource());
    }
}
